<template>
  <!-- 菜单权限对话框 -->
  <y-dialog v-model="dialogVisible" title="菜单权限" @before-show="handleDialogOpen">
    <!-- 表单区域 -->
    <q-form ref="formRef" @submit.prevent="submitForm" class="q-gutter-y-md">
      <!-- 卡片容器 -->
      <q-card flat bordered>
        <!-- 卡片操作区域：包含三个切换按钮 -->
        <q-card-actions class="q-px-md q-pt-md q-pb-none">
          <!-- 展开/折叠切换按钮 -->
          <q-toggle
            v-model="menuExpand"
            label="展开/折叠"
            color="primary"
            @update:model-value="handleCheckedTreeExpand"
          />
          <!-- 全选/全不选切换按钮 -->
          <q-toggle
            v-model="menuNodeAll"
            label="全选/全不选"
            color="primary"
            @update:model-value="handleCheckedTreeNodeAll"
          />
          <!-- 父子联动切换按钮 -->
          <q-toggle
            v-model="menuCheckStrictly"
            label="父子联动"
            color="primary"
            @update:model-value="handleCheckedTreeConnect"
          />
        </q-card-actions>

        <!-- 卡片内容区域 -->
        <q-card-section class="q-pt-none">
          <!-- 搜索框 -->
          <q-input
            v-model="filterText"
            outlined
            dense
            placeholder="搜索菜单..."
            clearable
            class="q-mb-md"
          >
            <template v-slot:prepend>
              <q-icon name="search" />
            </template>
          </q-input>

          <!-- 树形菜单组件 -->
          <q-tree
            ref="menuTreeRef"
            :nodes="menuOptions"
            node-key="id"
            label-key="label"
            :tick-strategy="menuCheckStrictly ? 'leaf' : 'strict'"
            v-model:ticked="checkedMenuKeys"
            :no-connectors="true"
            :default-expand-all="false"
            dense
            accordion
            children-key="children"
            :filter="filterText"
          >
            <!-- 自定义节点标题插槽 -->
            <template v-slot:default-header="prop">
              <div>
                <span>{{ prop.node.label }}</span>
              </div>
            </template>
          </q-tree>
        </q-card-section>
      </q-card>

      <!-- 表单操作按钮 -->
      <div class="flex justify-end q-gutter-sm q-mt-md">
        <q-btn label="取消" v-close-popup flat color="grey-7" :disable="loading" />
        <q-btn type="submitForm" label="保存" color="primary" :loading="loading" unelevated />
      </div>
    </q-form>
  </y-dialog>
</template>

<script setup>
import modal from '@/plugins/modal'
import { getRole, updateRole, roleMenuTreeselect } from '@/api/sys/role'

// 组件props定义
const props = defineProps({
  modelValue: Boolean, // 控制对话框显示
  roleId: { type: String, default: undefined }, // 角色ID
})

// 定义emit事件
const emit = defineEmits(['update:modelValue', 'success'])

// 计算属性：双向绑定对话框显示状态
const dialogVisible = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value),
})

// 响应式状态定义
const loading = ref(false) // 加载状态
const menuOptions = ref([]) // 菜单树数据
const filterText = ref('') // 搜索文本
const checkedMenuKeys = ref([]) // 选中的菜单keys
const menuTreeRef = ref(null) // 树组件引用
const menuExpand = ref(false) // 是否展开所有节点
const menuNodeAll = ref(false) // 是否全选
const menuCheckStrictly = ref(true) // 是否父子联动

/**
 * 对话框打开时的处理函数
 */
const handleDialogOpen = async () => {
  // 获取角色菜单树数据
  const response = await roleMenuTreeselect(props.roleId)
  menuOptions.value = response.data[0].menus // 设置菜单选项
  checkedMenuKeys.value = response.data[0].menu // 设置默认选中的菜单
}

/**
 * 处理树形菜单展开/折叠
 * @param {Boolean} value - 是否展开
 */
function handleCheckedTreeExpand(value) {
  value ? menuTreeRef.value.expandAll() : menuTreeRef.value.collapseAll()
}

/**
 * 处理全选/全不选
 * @param {Boolean} value - 是否全选
 */
function handleCheckedTreeNodeAll(value) {
  if (value) {
    // 全选
    if (menuCheckStrictly.value) {
      // 父子联动模式 - 全选所有叶子节点
      checkedMenuKeys.value = getLeafNodeKeys(menuOptions.value)
    } else {
      // 非父子联动模式 - 全选所有节点
      checkedMenuKeys.value = getAllNodeKeys(menuOptions.value)
    }
  } else {
    // 全不选
    checkedMenuKeys.value = []
  }
}

/**
 * 获取所有节点key（包括父节点和子节点）
 * @param {Array} nodes - 节点数组
 * @returns {Array} 所有节点的key数组
 */
function getAllNodeKeys(nodes) {
  let keys = []
  nodes.forEach((node) => {
    keys.push(node.id)
    if (node.children && node.children.length > 0) {
      keys = keys.concat(getAllNodeKeys(node.children))
    }
  })
  return keys
}

/**
 * 获取所有叶子节点key
 * @param {Array} nodes - 节点数组
 * @returns {Array} 所有叶子节点的key数组
 */
function getLeafNodeKeys(nodes) {
  let keys = []
  nodes.forEach((node) => {
    if (!node.children || node.children.length === 0) {
      keys.push(node.id)
    } else {
      keys = keys.concat(getLeafNodeKeys(node.children))
    }
  })
  return keys
}

/**
 * 处理父子联动模式切换
 * @param {Boolean} value - 是否启用父子联动
 */
function handleCheckedTreeConnect(value) {
  menuCheckStrictly.value = value
}

/**
 * 提交表单
 */
async function submitForm() {
  loading.value = true
  try {
    // 获取角色信息
    const response = await getRole(props.roleId)
    // 准备更新数据
    const formData = {
      ...response.data,
      menu: checkedMenuKeys.value,
    }
    // 更新角色
    await updateRole(formData)

    modal.msgSuccess('操作成功！')
    dialogVisible.value = false
  } catch (error) {
    modal.msgError('操作失败', error)
  } finally {
    loading.value = false
  }
}
</script>
